home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib25 / _addsubd.cpp next >
Text File  |  1992-12-12  |  6KB  |  227 lines

  1. |
  2. | double floating point add/subtract routine
  3. |
  4. #ifndef __M68881__
  5.     .text
  6.     .even
  7.     .globl    __subdf3, ___subdf3
  8.     .globl    __adddf3, ___adddf3
  9. #ifndef    sfp004
  10. |
  11. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  12. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  13. | patched by Olaf Flebbe (flebbe@tat.physik.uni-tuebingen.de)
  14. |
  15. | Revision 1.3.3 olaf 11-92 :
  16. |  + changed to get rid of rounding bits. a sticky register (d3) is
  17. |    sufficient. 
  18. | Revision 1.3.2 olaf 10-92 :
  19. |  + increased comparson by one again. (Dont understand, but it works)
  20. |  + corrected negation of rounding bits and mantissa
  21. |     >enquire now detects correct IEEE precision
  22. |     >paranoia now qualifies add/sub as correctly rounded
  23. |
  24. | Revision 1.3.1 olaf 10-92 :
  25. |  + increased comparison of exponents by one.
  26. |  + initialized sticky byte
  27. |  + corrected handling of rounding bits
  28. |     >paranoia now detects no SERIOUS DEFECTS any more
  29. |     ** Patches need _normdf Rev 1.6.1 (or higher) **
  30. |
  31. | Revision 1.3, kub 01-90 :
  32. | added support for denormalized numbers
  33. |
  34. | Revision 1.2, kub 01-90 :
  35. | replace far shifts by swaps to gain speed
  36. |
  37. | Revision 1.1, kub 12-89 :
  38. | Ported over to 68k assembler
  39. |
  40. | Revision 1.0:
  41. | original 8088 code from P.S.Housel
  42.  
  43. __subdf3:
  44. ___subdf3:
  45.     eorb    #0x80,sp@(12)    | reverse sign of v
  46. __adddf3:
  47. ___adddf3:
  48.     lea    sp@(4),a0    | pointer to u and v parameter
  49.     moveml    d2-d7,sp@-    | save registers
  50.     moveml    a0@,d4-d5/d6-d7    | d4-d5 = v, d6-d7 = u
  51.  
  52.     movel    d6,d0        | d0 = u.exp
  53.     swap    d0
  54.     movel    d6,d2        | d2.h = u.sign
  55.     movew    d0,d2
  56.     lsrw    #4,d0
  57.     andw    #0x07ff,d0    | kill sign bit
  58.  
  59.     movel    d4,d1        | d1 = v.exp
  60.     swap    d1
  61.     eorw    d1,d2        | d2.l = u.sign ^ v.sign
  62.     lsrw    #4,d1
  63.     andw    #0x07ff,d1    | kill sign bit
  64.  
  65.     andl    #0x0fffff,d6    | remove exponent from u.mantissa
  66.     tstw    d0        | check for zero exponent - no leading "1"
  67.     beq    0f
  68.     orl    #0x100000,d6    | restore implied leading "1"
  69.     bra    1f
  70. 0:    addw    #1,d0        | "normalize" exponent
  71. 1:
  72.     andl    #0x0fffff,d4    | remove exponent from v.mantissa
  73.     tstw    d1        | check for zero exponent - no leading "1"
  74.     beq    0f
  75.     orl    #0x100000,d4    | restore implied leading "1"
  76.     bra    1f
  77. 0:    addw    #1,d1        | "normalize" exponent
  78. 1:
  79.     clrl    d3        | init sticky register
  80.     negw    d1        | d1 = u.exp - v.exp
  81.     addw    d0,d1
  82.     beq    5f        | exponents are equal - no shifting neccessary
  83.     bgt    1f        | not equal but no exchange neccessary
  84.     exg    d4,d6        | exchange u and v
  85.     exg    d5,d7
  86.     subw    d1,d0        | d0 = u.exp - (u.exp - v.exp) = v.exp
  87.     negw    d1
  88.     tstw    d2        | d2.h = u.sign ^ (u.sign ^ v.sign) = v.sign
  89.     bpl    1f
  90.     bchg    #31,d2
  91. 1:
  92.     cmpw    #55,d1        | is u so much bigger that v is not
  93.     bge    7f        | significant ?
  94. |
  95. | shift mantissa left two digits, to allow cancellation of
  96. | most significant digit, while gaining an additional digit for
  97. | rounding.
  98. |
  99.     moveql  #1,d3    
  100. 2:    addl    d7,d7
  101.     addxl    d6,d6
  102.     subw    #1,d0        | decrement exponent
  103.     subw    #1,d1        | decrement counter
  104.     dbeq    d3,2b
  105.     clrl    d3
  106. |
  107. | now shift other mantissa right as fast as possible (almost).
  108. |
  109. 3:    
  110.     cmpw    #16,d1        | see if fast rotate possible
  111.     blt    4f
  112.     orw    d5,d3        | set sticky word
  113.     movew    d4,d5        | rotate by swapping register halfs
  114.     swap    d5
  115.     clrw    d4
  116.     swap    d4
  117.     subw    #16,d1
  118.     bra    3b
  119.  
  120. 0:    moveb   d5,d2        | use d2.b as scratch
  121.     andb    #1,d2        | test if 1 is shifted out
  122.     orb    d2,d3        | and put it in sticky 
  123.     lsrl    #1,d4        | shift v.mant right the rest of the way
  124.     roxrl    #1,d5        | to line it up with u.mant
  125. 4:    dbra    d1,0b        | loop
  126.     
  127. 5:
  128.     tstw    d2        | are the signs equal ?
  129.     bpl    6f        | yes, no negate necessary
  130. |
  131. | negate secand mantissa. One has to check the sticky word in order
  132. | to correct the twos complement.
  133. |
  134.     tstw    d3        | 
  135.     beq     9f        | No cerrection necessary
  136.     clrl    d1
  137.     addql   #1,d5
  138.     addxl   d1,d4
  139. 9:    negl    d5
  140.     negxl    d4
  141.         
  142. 6:
  143.     addl    d5,d7        | u.mant = u.mant + v.mant
  144.     addxl    d4,d6
  145.     bcs    7f        | need not negate
  146.     tstw    d2        | opposite signs ?
  147.     bpl    7f        | do not need to negate result
  148.  
  149.     negl    d7
  150.     negxl    d6
  151.     notl    d2        |     switch sign
  152. 7:
  153.     movel    d6,d4        | move result for normalization
  154.     movel    d7,d5
  155.     clrl    d1
  156.     tstl    d3
  157.     beq     8f
  158.     moveql   #-1,d1
  159. 8:    swap    d2        | put sign into d2 (exponent is in d0)
  160.     jmp    norm_df        | leave registers on stack for norm_df
  161. #else    sfp004
  162. | double precision floating point stuff for Atari-gcc using the SFP004
  163. | developed with gas
  164. |
  165. | double floating point add/subtract routine
  166. |
  167. | M. Ritzert (mjr at dmzrzu71)
  168. |
  169. | 4.10.1990
  170. |
  171. | no NAN checking implemented since the 68881 treats this situation "correct",
  172. | i.e. according to IEEE
  173.  
  174. | addresses of the 68881 data port. This choice is fastest when much data is
  175. | transferred between the two processors.
  176.  
  177. comm =     -6
  178. resp =    -16
  179. zahl =      0
  180.  
  181. | waiting loop ...
  182. |
  183. | wait:
  184. | ww:    cmpiw    #0x8900,a0@(resp)
  185. |     beq    ww
  186. | is coded directly by
  187. |    .long    0x0c688900, 0xfff067f8
  188.  
  189. __subdf3:
  190. ___subdf3:
  191. | double precision subtraction
  192. | sub second arg from fp0
  193.     lea    0xfffffa50:w,a0
  194.     movew    #0x5400,a0@(comm)    | load first argument to fp0
  195.     cmpiw    #0x8900,a0@(resp)    | check
  196.     movel    a7@(4),a0@
  197.     movel    a7@(8),a0@
  198.     movew    #0x5428,a0@(comm)
  199.     .long    0x0c688900, 0xfff067f8
  200.     movel    a7@(12),a0@
  201.     movel    a7@(16),a0@
  202.     movew    #0x7400,a0@(comm)    | result to d0/d1
  203.     .long    0x0c688900, 0xfff067f8
  204.     movel    a0@,d0
  205.     movel    a0@,d1
  206.      rts
  207.  
  208. __adddf3:
  209. ___adddf3:
  210.     lea    0xfffffa50:w,a0
  211.     movew    #0x5400,a0@(comm)        | load fp0
  212.     cmpiw    #0x8900,a0@(resp)        | got it?
  213.     movel    a7@(4),a0@            | take a hi from stack to FPU
  214.     movel    a7@(8),a0@            | take a lo from stack to FPU
  215.     movew    #0x5422,a0@(comm)        | add second arg to fp0
  216.     .long    0x0c688900, 0xfff067f8
  217.     movel    a7@(12),a0@            | move b hi from stack to FPU
  218.     movel    a7@(16),a0@            | move b lo from stack to FPU
  219.     movew    #0x7400,a0@(comm)        | result to d0/d1
  220.     .long    0x0c688900, 0xfff067f8
  221.     movel    a0@,d0                | download result
  222.     movel    a0@,d1                | download result
  223.      rts
  224. #endif    sfp004
  225. #endif    __M68881__
  226.